package dS.ProjectGPS;

import dS.ProjectGPS.*;
import dS.ProjectGPS.Bluetooth.*;
import dS.ProjectGPS.LeicaOWI.*;
import dS.ProjectGPS.GPS.*;
import dS.ProjectGPS.NTrip.*;

import java.io.*;
import javax.microedition.io.*;
import javax.bluetooth.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

/**
 *
 * <p>Title: ProjectGPSme </p>
 *
 * <p>Description: Main class of program. Provides creation, pausing and
 *                 destruction of program. Also provides a main user menu and
 *                 creation of Bluetooth SPP connection.</p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>@author David So</p>
 *
 * @version 1.0
 */

public class ProjectGPSme extends MIDlet implements CommandListener {

  // singleton self instance
  public static ProjectGPSme instance = null;
  private Display display = Display.getDisplay(this);

  private final static Command CMD_EXIT = new Command("Exit", Command.EXIT, 10);
  private final static Command CMD_BACK = new Command("Back", Command.BACK, 10);

  // Main menu variables
  public static List mainMenu;
  private static final String[] mainMenuNames = {"Connect (BT)", "Navigator (NMEA)",
                                   "Controller (OWI)", "Receiver (NTRIP)", "About", "Exit"
  };
  Ticker mainMenuTick = new Ticker("Please connect then select function.");


  // 'About' screen variables
  private Form about = new Form("About");
  private Image logo;
  private ImageItem logoItem;
  private StringItem aboutText = new StringItem("", "\nProvides a framework and implementation to exploring the possibilites made by combining: GPS, Bluetooth and mobile phones.\n\n");
  private StringItem aboutText2 = new StringItem("Requirements",
     "\n - MIDP 2.0\n - Bluetooth API (JSR-82)\n\n");
  private StringItem aboutText3 = new StringItem("Acknowledgements", "\nI would like to thank Chris Rizos, Thomas Yan and Joel Barnes for their dedication and continual support on this thesis.\n\n");
  private StringItem aboutText4 = new StringItem("Contact",
     "\nDavid So\ndaveso@cse.unsw.edu.au\nhttp://www.davidso.com\n\n");

  // BLUElet component
  // To perform device discovery, device selection and service discovery
  BLUElet bluelet = null;
  BluetoothScreen screen = new BluetoothScreen();
  private NTripClient ntripClient = null;

  private Navigator navigator = new Navigator(display);
  private Controller controller = new Controller(display);

  StreamConnection btConn = null;
  InputStream btIn = null;
  PrintStream btOut = null;



  public ProjectGPSme() {

    instance = this;
    log("Press SEARCH to find device.");

    // Initialise the main menu
    mainMenu = new List("ProjectGPSme", Choice.IMPLICIT, mainMenuNames, null);
    mainMenu.setTicker(mainMenuTick);

    try{
      logo = Image.createImage("/logo.png");
    } catch (Exception e){
      System.out.println("Error loading logo image");
    }

    logoItem = new ImageItem("", logo, ImageItem.LAYOUT_CENTER, "");

    // Initialise the about screen - ie. add text
    about.append(logoItem);
    about.append(aboutText);
    about.append(aboutText2);
    about.append(aboutText3);
    about.append(aboutText4);

    // create a instance of BLUElet
    // the first parameter is host MIDlet
    // this second parameter is CommandListener (also this class)
    bluelet = new BLUElet(this, this);

  }

  protected void startApp() throws MIDletStateChangeException {

    // do BLUElet initialization
    bluelet.startApp();

    display.setCurrent(mainMenu);
    mainMenu.setCommandListener(this);

  }

  protected void pauseApp() {
    // do Bluelet pause
    bluelet.pauseApp();
  }

  protected void destroyApp(boolean _boolean) throws MIDletStateChangeException {

    // Close Bluetooth connection
    if (btConn != null){
      try{
        btIn.close();
        btConn.close();
      } catch (Exception e){
         // Do nothing
       }
     }

     // do Bluelet destroy
    bluelet.destroyApp(_boolean);
    notifyDestroyed();
  }

  public void commandAction(Command c, Displayable d) {
    if (d.equals(mainMenu)) {

      //Retrieving the selected index from the list
      switch (((List) d).getSelectedIndex()) {
        case 0: { // Bluetooth Setup
          display.setCurrent(screen);
          screen.setCommandListener(this);
          break;
        }
        case 1: { // Navigator
          if(btIn != null){
            navigator.nmeaReader.rawIn = btIn;
            navigator.nmeaReader.rawSet = true;
          } else {
            navigator.nmeaReader.rawSet = false;
          }
          display.setCurrent(navigator);
          break;
        }
        case 2: { // Controller
          controller.owiAgent.in = btIn;
          controller.owiAgent.out = btOut;
          display.setCurrent(controller);
          break;
        }
        case 3: { // NTRIP Client
          ntripClient = new NTripClient(display);

          if(btOut != null){
            ntripClient.serialOutStream = btOut;
            ntripClient.serialOut = true;
          } else {
            ntripClient.serialOut = false;
          }
          display.setCurrent(ntripClient.menu);
          break;
        }
        case 4: { // About
          about.addCommand(CMD_BACK);
          about.setCommandListener(this);
          display.setCurrent(about);
          break;
        }
        case 5: { // Exit
          try {
            destroyApp(true);
          }
          catch (Exception e) {
          }
          break ;
        }
      }

    }
    else if (d.equals(screen) && c.getLabel().equals("Search")) {
      // when user press Search, we invoke Bluelet to
      // perform device discovery, then we should switch the screen
      // to Bluelet Devices screen for user to select an device

      System.out.println("Starting Bluetooth Search");
      bluelet.startInquiry(DiscoveryAgent.GIAC, new UUID[] {new UUID(0x1101)});
      display.setCurrent(bluelet.getUI());

    }
    else if (c.equals(BLUElet.SELECTED)) {
      // handle event that user has selected a device for service discovery

    }
    else if (c.equals(BLUElet.BACK)) {
      // handle event that user has press Back button on Bluetooth Devices screen
      // usually, we switch back to host application screen

      display.setCurrent(mainMenu);
    }
    else if (c.equals(BLUElet.COMPLETED)) {
      // handle event that service discovery is completed
      // usually we pass control back to host MIDlet and connect
      // to remote service for perform network communication

      System.out.println("Bluelet Completed");
      display.setCurrent(screen);

      ServiceRecord r = bluelet.getFirstDiscoveredService();

      String url = r.getConnectionURL(ServiceRecord.AUTHENTICATE_NOENCRYPT, false);
      log("url: " + url);

      System.out.println(url);


      try{
        btConn = (StreamConnection) Connector.open(url);
        btIn = btConn.openInputStream();
        btOut = new PrintStream(btConn.openOutputStream());

        log("Connected. To continue, press 'Back'.");

        // Used to show incoming BT data - delete later
     /*   int incoming = btIn.read();
        String line = new String();

       //  for(int i = 0; i<10; i++){
        while (true) {
          btOut.println("Quynh");
          btOut.flush();
          if ((char) incoming == '\n') {
            log(line);
            line = "";
          }
          else {
            line += (char) incoming;
          }
          incoming = btIn.read();
        }
       // log(line); */

      } catch (Exception e){
        log("Error: Could not connect");
        log(e.getMessage());
        log("Try resetting Bluetooth device");
      }
    }

    else if (c.getLabel().equals("Back")) {
      display.setCurrent(mainMenu);
      mainMenu.setCommandListener(this);
    }
  }

  /**
   * An utility function to write log to screen
   * @param m String
   */
  public static void log(String m) {
    instance.screen.add(m);
    instance.screen.repaint();
  }

}
